package output;

import PackagePoseidon.DirectionDataSubscriber;
import PackagePoseidon.SpeedDataSubscriber;
import PackagePoseidon.AngulationDataSubscriber;
import PackagePoseidon.DistanceDataSubscriber;
import PackagePoseidon.EnvironmentDataSubscriber;
import PackagePoseidon.ForceDataSubscriber;
import PackagePoseidon.RobotDataSubscriber;
import ops.Participant;
import ops.Topic;

/**
 *
 * Francesco Lilli 01/08/2010
 *
 * The class OPSInterface is needed to make the output (project OutputNew)
 * and the simulator (project Poseidon_Inter) communicate each other.
 * This class contains all the needed methods to receive the information about
 * the direction of the robot, the speed of the robot, the angulation of the
 * robot, the distance of the robot from the starting point, the environment, 
 * the applied forces and the main characteristics of the robot into OPS.
 *
 */
public class OPSInterface {

    //Used topics
    Topic directionTopic;
    Topic speedTopic;
    Topic angulationTopic;
    Topic distanceTopic;
    Topic environmentTopic;
    Topic forceTopic;
    Topic robotTopic;

    //Used data
    DirectionDataSubscriber subDir;
    SpeedDataSubscriber subSpe;
    AngulationDataSubscriber subAng;
    DistanceDataSubscriber subDis;
    EnvironmentDataSubscriber subEnv;
    ForceDataSubscriber subFor;
    RobotDataSubscriber subRob;

    /**
     * Francesco Lilli 01/08/2010
     *
     * The constructor of the interface. When an OPSInterface is created, the
     * methid initOPS() is immediately called.
     *
     * @param
     */
    public OPSInterface() {
        initOPS();
    }
    
    /**
     * Francesco Lilli 01/08/2010
     *
     * The method initializes all the needed parameters for OPS. It specifies:
     * - the source where to get access to the Participants;
     * - the Topics, what arguments we're going to talk about. In a Topic we can
     *   take into account several IDL data types;
     * - the Participants, who's going to use OPS in order to send/receive
     *   the needed information. In this case all of them are subscribers, so
     *   they just receive.
     *
     * @param
     * @return
     */
    public void initOPS() {

         //Initialize participants
         Participant participant = Participant.getInstance("PoseidonDomain");
         participant.addTypeSupport(new OPSIDLPoseidonFinal.OPSIDLPoseidonFinalTypeFactory());

         //Create topics
         directionTopic = participant.createTopic("DirectionTopic");
         speedTopic = participant.createTopic("SpeedTopic");
         angulationTopic = participant.createTopic("AngulationTopic");
         distanceTopic = participant.createTopic("DistanceTopic");
         environmentTopic = participant.createTopic("EnvironmentTopic");
         forceTopic = participant.createTopic("ForceTopic");
         robotTopic = participant.createTopic("RobotTopic");

         //Create subscribers
         subDir = new DirectionDataSubscriber(directionTopic);
         subSpe = new SpeedDataSubscriber(speedTopic);
         subAng = new AngulationDataSubscriber(angulationTopic);
         subDis = new DistanceDataSubscriber(distanceTopic);
         subEnv = new EnvironmentDataSubscriber(environmentTopic);
         subFor = new ForceDataSubscriber(forceTopic);
         subRob = new RobotDataSubscriber(robotTopic);     
    }

    /**
     * Francesco Lilli 01/08/2010
     *
     * The method adds observers for the Output GUI. This is made of three
     * panels, and each of them has to observe what's going on OPS.
     *
     * @param ctrl - a Control Panel, where all the information (values about
     *               the physics and the robot parameters) has to be written.
     *         dir - a Direction Panel, where will be possible to see the
     *               joystick movements.
     *         out - an Output Panel, where a little square is used to indicate
     *               the position of the robot.
     * @return
     */
    public void addObserverOPS(ControlPanel2 ctrl, Direction dir, OutputPanel out) {

        //adds an observer for each subscriber
        subDir.addObserver(dir);
        subSpe.addObserver(ctrl);
        subAng.addObserver(ctrl);
        subDis.addObserver(ctrl);
        subDis.addObserver(out);
        subEnv.addObserver(ctrl);
        subFor.addObserver(ctrl);
        subRob.addObserver(ctrl);

        //the subscribers start to work
        subDir.start();
        subSpe.start();
        subAng.start();
        subDis.start();
        subEnv.start();
        subFor.start();
        subRob.start();
    }
}
